(function() {
  'use strict';

  angular.module('DeployTool.tasktrack')
    .factory('TaskTrackService', ['CommonService', '$filter', TaskTrackService]);

  function TaskTrackService(CommonService, $filter) {

    var statusStyle = {
      'unstart': {
        'progress': '',
        'ring': '#dedede'
      },
      'exception': {
        'progress': 'progress-bar-danger',
        'ring': '#e74c3c'
      },
      'handing': {
        'progress': 'progress-bar-info',
        'ring': '#2392f7'
      },
      'done': {
        'progress': 'progress-bar-success',
        'ring': '#5bbc8a'
      },
      'overtime': {
        'progress': 'progress-bar-warning',
        'ring': '#f9ab5e'
      },
      'fallback': {
        'progress': 'progress-bar-disable',
        'ring': '#97a1b0'
      },
    };
    var mincell = 6;
    var minpixel = 22;

    var service = {
      getTaskPlanList: getTaskPlanList,
      getProjectStatus: getProjectStatus,
      addProject: addProject,
      updateProject: updateProject,
      downloadFile: downloadFile,
      delTaskPlan: delTaskPlan,
      getTaskPlanInfo: getTaskPlanInfo,
      handlePlanData: handlePlanData,
      refreshPartInfo: refreshPartInfo,
      handleDetail: handleDetail,
      translateChangeStatus: translateChangeStatus,
      translateFallbackStatus: translateFallbackStatus,
      translateProjectStatus: translateProjectStatus,
      getChangeList: getChangeList,
      refreshProjectInfo: refreshProjectInfo,
    };

    return service;

    ////////////////////

    function getProjectStatus() {
      return { 1: '筹备中', 2: '执行中', 3: '已完成', 4: '回退中', 5: '已回退' };
    }

    function getTaskPlanList(data) {
      return CommonService.get('project/search', data);
    }

    function addProject(data) {
      return CommonService.uploadFile('project/add', data);
    }

    function updateProject(data) {
      return CommonService.uploadFile('project/edit', data);
    }

    function downloadFile(taskId) {
      return CommonService.getUrlPrefix() + 'project/download/' + taskId;
    }

    function delTaskPlan(taskId) {
      return CommonService.get('project/delete/' + taskId);
    }

    function getTaskPlanInfo(taskId) {
      return CommonService.get('project/detail/' + taskId);
    }

    function getChangeList(taskId) {
      return CommonService.get('fallbackTask/getList/' + taskId);
    }

    function translateProjectStatus(data) {
      return CommonService.post('/project/changeStatus', data);
    }

    function translateChangeStatus(taskId, type) {
      return CommonService.post('changeTask/changeStatus/' + taskId + '/' + type);
    }

    function translateFallbackStatus(taskId, type) {
      return CommonService.post('fallbackTask/changeStatus/' + taskId + '/' + type);
    }

    function handlePlanData(planData) {
      var planInfo = {};
      planInfo.projectName = planData.projectName;
      planInfo.status = planData.status;
      planInfo.dateText = planData.dateText;
      planInfo.noEnum = planData.noEnum;
      planInfo.changeGroupList = [];
      planInfo.fallbackList = [];

      var startTime = handleTimeAxis(planData, planInfo);
      handleChangeTaskData(planData.changeList, planInfo.changeGroupList, startTime, planInfo.status);
      handleFallbackTaskData(planData.fallbackList, planInfo.fallbackList, startTime);

      planInfo.startTime = startTime;
      return planInfo;
    }

    function handleTimeAxis(planData, planInfo) {
      var changeExpectStartTimes = _.map(planData.changeList, 'expectStartTime');
      var changeExpectEndTimes = _.map(planData.changeList, 'expectEndTime');
      var changeStartTimes = _.map(planData.changeList, 'startTime');
      var changeEndTimes = _.map(planData.changeList, 'endTime');
      var fallbackExpectStartTimes = _.map(planData.fallbackList, 'expectStartTime');
      var fallbackExpectEndTimes = _.map(planData.fallbackList, 'expectEndTime');
      var fallbackStartTimes = _.map(planData.fallbackList, 'startTime');
      var fallbackEndTimes = _.map(planData.fallbackList, 'endTime');

      var times = _.concat(changeExpectStartTimes, changeExpectEndTimes, changeStartTimes, changeEndTimes, fallbackExpectStartTimes, fallbackExpectEndTimes, fallbackStartTimes, fallbackEndTimes);
      times = _.remove(_.sortBy(_.uniq(times)), function(time) { return time; });

      var startTime = _.head(times);
      var lastTime = _.last(times);

      // (lastTime- startTime)/1000/60/60  小时时间间隔
      planInfo.timeAxis = {};

      var hourInterval = Math.ceil((lastTime - startTime) / 1000 / 60 / 60);
      var startDate = new Date(startTime);
      startDate.setMinutes(0);
      startDate.setSeconds(0);
      startDate.setMilliseconds(0);

      for (var i = 0; i <= hourInterval; i++) {
        var hourAxis = startDate.getTime() - 0 + i * 1000 * 60 * 60;
        planInfo.timeAxis[hourAxis] = [
          // '01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
          // '11', '12', '13', '14', '15', '16', '17', '18', '19', '20',
          // '21', '22', '23', '24', '25', '26', '27', '28', '29', '30',
          // '31', '32', '33', '34', '35', '36', '37', '38', '39', '40',
          // '41', '42', '43', '44', '45', '46', '47', '48', '49', '50',
          // '51', '52', '53', '54', '55', '56', '57', '58', '59', '60',
          '06', '12', '18', '24', '30', '36', '42', '48', '54', '60'
          // '05', '10', '15', '20', '25', '30', '35', '40', '45', '50', '55', '60'
        ];
      }

      return startDate.getTime();
    }

    function handleChangeTaskData(dataList, groupList, startTime, status) {
      var nos = _.orderBy(_.uniq(_.map(dataList, 'no')));
      _.forEach(nos, function(no) {
        var list = _.filter(dataList, { 'no': no });

        var useTime = 0;
        var finishCount = 0;

        _.forEach(list, function(task) {

          var taskStatus = '';
          if (!task.startTime) {
            taskStatus = 'unstart';
          } else if (task.status === false) {
            taskStatus = 'exception';
          } else if (!task.endTime) {
            taskStatus = 'handing';
          } else if (task.endTime > task.expectEndTime) {
            taskStatus = 'overtime';
          } else {
            taskStatus = 'done';
          }

          if (task.endTime && task.startTime) {
            task.useTime = (task.endTime - task.startTime) / 1000;
            useTime += task.useTime;
          }

          if (task.endTime) {
            finishCount++;
          }

          var style = handleProgressStyle(task, startTime, status);

          task.progress = {
            'status': taskStatus,
            'style': style,
          };
        });

        var projectStatus = '';

        var startList = _.reject(list, function(t) { return t.progress.status == 'unstart'; });
        var unDoneList = _.reject(list, function(t) { return t.progress.status == 'done' || t.progress.status == 'overtime'; });
        var exceptionList = _.filter(list, function(t) { return t.progress.status == 'exception'; });

        if (status == '4' || status == '5') {
          if (exceptionList.length > 0) {
            projectStatus = 'exception';
          } else {
            projectStatus = 'fallback';
          }
        } else if (startList.length === 0) {
          projectStatus = 'unstart';
        } else if (exceptionList.length > 0) {
          projectStatus = 'exception';
        } else if (unDoneList.length === 0) {
          projectStatus = 'done';
        } else {
          projectStatus = 'handing';
        }

        var _startTime = _.remove(_.sortBy(_.map(list, 'startTime')), null)[0];
        var _endTime = _.remove(_.sortBy(_.map(list, 'endTime')), null).pop();
        var _expectStartTime = _.sortBy(_.map(list, 'expectStartTime'))[0];
        var _expectEndTime = _.sortBy(_.map(list, 'expectEndTime')).pop();

        if (_endTime > _expectEndTime) {
          projectStatus = 'overtime';
        }

        var outstyle = {
          'margin-left': (_expectStartTime - startTime) / 1000 / 60 / mincell * minpixel + 'px',
          'width': (_expectEndTime - _expectStartTime) / 1000 / 60 / mincell * minpixel + 'px'
        };
        var instyle = {
          'margin-left': (_startTime - _expectStartTime) / 1000 / 60 / mincell * minpixel + 'px',
          'width': (_endTime - _startTime) / 1000 / 60 / mincell * minpixel + 'px'
        };

        var rotateAngle = parseInt(finishCount / list.length * 100);
        var ringstyle = '';
        if (rotateAngle < 50) {
          ringstyle = {
            'background-image': 'linear-gradient(90deg, #c1d2e1 50%, transparent 50%, transparent), ' +
              'linear-gradient(' + (3.6 * rotateAngle + 90) + 'deg, ' + statusStyle[projectStatus].ring + ' 50%, #c1d2e1 50%, #c1d2e1)'
          };
        } else {
          ringstyle = {
            'background-image': 'linear-gradient(' + (-90 + 3.6 * (rotateAngle - 50)) + 'deg, ' + statusStyle[projectStatus].ring + ' 50%, transparent 50%, transparent), ' +
              'linear-gradient(270deg, ' + statusStyle[projectStatus].ring + ' 50%, #c1d2e1 50%, #c1d2e1)'
          };
        }

        groupList.push({
          'no': no,
          'projectStatus': projectStatus,
          'isStart': !!_startTime,
          'useTime': useTime,
          'finishCount': finishCount,
          'list': list,
          'progress': {
            'status': projectStatus,
            'class': statusStyle[projectStatus].progress,
            'style': {
              'outstyle': outstyle,
              'instyle': instyle,
              'ringstyle': ringstyle,
            }
          }
        });
      });
    }

    function handleFallbackTaskData(dataList, fallbackList, startTime) {
      _.forEach(dataList, function(task) {

        var taskStatus = '';
        if (!task.startTime) {
          taskStatus = 'unstart';
        } else if (!task.endTime) {
          taskStatus = 'handing';
        } else {
          taskStatus = 'done';
        }

        var style = handleProgressStyle(task, startTime);
        task.useTime = (task.endTime - task.startTime) / 1000;
        task.progress = {
          'status': taskStatus,
          'style': style,
        };

        fallbackList[task.no] = task;
      });
    }

    function handleProgressStyle(task, startTime, status) {

      var outstyle = {
        'margin-left': (task.expectStartTime - startTime) / 1000 / 60 / mincell * minpixel + 'px',
        'width': (task.expectEndTime - task.expectStartTime) / 1000 / 60 / mincell * minpixel + 'px'
      };

      var isOvertime = false,
        inTimeStyle, outTimeStyle, iconStyle;

      if (task.endTime > task.expectEndTime) {
        isOvertime = true;
        if (task.startTime > task.expectEndTime) {
          outTimeStyle = {
            'margin-left': (task.startTime - task.expectStartTime) / 1000 / 60 / mincell * minpixel + 'px',
            'width': (task.endTime - task.startTime) / 1000 / 60 / mincell * minpixel + 'px'
          };
        } else {
          inTimeStyle = {
            'margin-left': (task.startTime - task.expectStartTime) / 1000 / 60 / mincell * minpixel + 'px',
            'width': (task.expectEndTime - task.startTime) / 1000 / 60 / mincell * minpixel + 'px'
          };
          outTimeStyle = {
            'margin-left': (task.expectEndTime - task.expectStartTime) / 1000 / 60 / mincell * minpixel + 'px',
            'width': (task.endTime - task.expectEndTime) / 1000 / 60 / mincell * minpixel + 'px'
          };
        }
        iconStyle = { 'margin-left': (task.endTime - task.expectStartTime) / 1000 / 60 / mincell * minpixel + 15 + 'px' };
      } else {
        inTimeStyle = {
          'margin-left': (task.startTime - task.expectStartTime) / 1000 / 60 / mincell * minpixel + 'px',
          'width': (task.endTime - task.startTime) / 1000 / 60 / mincell * minpixel + 'px'
        };
        iconStyle = { 'margin-left': (task.expectEndTime - task.expectStartTime) / 1000 / 60 / mincell * minpixel + 15 + 'px' };
      }

      var style = {
        'outstyle': outstyle,
        'instyle': {
          'isOvertime': isOvertime,
          'inTimeStyle': {
            'class': statusStyle.done.progress,
            'style': inTimeStyle
          },
          'outTimeStyle': {
            'class': statusStyle.overtime.progress,
            'style': outTimeStyle
          },
          'iconStyle': iconStyle
        }
      };

      if (status == '4' || status == '5') {
        style.instyle.inTimeStyle.class = statusStyle.fallback.progress;
        style.instyle.outTimeStyle.class = statusStyle.fallback.progress;
      }

      return style;
    }

    function refreshPartInfo(taskPlanInfo, taskPlanData) {
      var _taskPlanInfo = handlePlanData(taskPlanData);
      if (!_.isEqual(taskPlanInfo, _taskPlanInfo)) {
        if (!_.isEqual(taskPlanInfo.status, _taskPlanInfo.status)) { taskPlanInfo.status = _taskPlanInfo.status; }
        if (!_.isEqual(taskPlanInfo.timeAxis, _taskPlanInfo.timeAxis)) { taskPlanInfo.timeAxis = _taskPlanInfo.timeAxis; }
        //changeGroupList
        if (!_.isEqual(taskPlanInfo.changeGroupList, _taskPlanInfo.changeGroupList)) {
          _.forEach(taskPlanInfo.changeGroupList, function(changeGroup) {
            var _changeGroup = _.find(_taskPlanInfo.changeGroupList, { 'no': changeGroup.no });
            if (!_.isEqual(changeGroup, _changeGroup)) {
              if (!_.isEqual(changeGroup.finishCount, _changeGroup.finishCount)) { changeGroup.finishCount = _changeGroup.finishCount; }
              if (!_.isEqual(changeGroup.useTime, _changeGroup.useTime)) { changeGroup.useTime = _changeGroup.useTime; }
              if (!_.isEqual(changeGroup.progress, _changeGroup.progress)) { changeGroup.progress = _changeGroup.progress; }
              if (!_.isEqual(changeGroup.list, _changeGroup.list)) {
                _.forEach(changeGroup.list, function(change) {
                  var _change = _.find(_changeGroup.list, { 'changeId': change.changeId });
                  if (!_.isEqual(change, _change)) {
                    change.endTime = _change.endTime;
                    change.expectEndTime = _change.expectEndTime;
                    change.expectStartTime = _change.expectStartTime;
                    change.startTime = _change.startTime;
                    change.status = _change.status;
                    change.useTime = _change.useTime;
                    change.progress = _change.progress;
                  }
                });
              }
            }
          });
        }
        //fallbackGroupList
        if (!_.isEqual(taskPlanInfo.fallbackList, _taskPlanInfo.fallbackList)) {
          _.forEach(taskPlanInfo.fallbackList, function(fallback) {
            if (fallback) {
              var _fallback = _.find(_taskPlanInfo.fallbackList, { 'fallbackId': fallback.fallbackId });
              if (!_.isEqual(fallback, _fallback)) {
                if (!_.isEqual(fallback.useTime, _fallback.useTime)) { fallback.useTime = _fallback.useTime; }
                if (!_.isEqual(fallback.progress, _fallback.progress)) { fallback.progress = _fallback.progress; }
              }
            }
          });
        }
      }
    }

    function handleDetail(detail) {
      var projectInfo = detail;
      _.forEach(projectInfo.changeList, function(n) {
        if (!n.startTime) {
          n.timeSpent = '未开始';
        } else if (!n.endTime) {
          n.timeSpent = '未完成';
        } else {
          n.timeSpent = $filter('timeTransform')((n.endTime - n.startTime) / 1000);
        }
      });

      _.forEach(projectInfo.fallbackList, function(n) {
        if (!n.startTime) {
          n.timeSpent = '未开始';
        } else if (!n.endTime) {
          n.timeSpent = '执行中';
        } else {
          n.timeSpent = $filter('timeTransform')((n.endTime - n.startTime) / 1000);
        }
      });

      projectInfo.isFallbacking = projectInfo.status == 4;
      projectInfo.changeGroup = _.groupBy(projectInfo.changeList, 'no');
      projectInfo.expectStartTime = _.orderBy(projectInfo.changeList, 'expectStartTime')[0].expectStartTime;
      delete projectInfo.changeList;
      initToggleStatus(projectInfo);
      return projectInfo;
    }

    function initToggleStatus(projectInfo) {
      projectInfo.isFallbackOpen = projectInfo.status == '4' || projectInfo.status == '5';
      projectInfo.isChangeOpen = !projectInfo.isFallbackOpen;
      projectInfo.changeOpenStatus = _.fill(new Array(Object.keys(projectInfo.changeGroup).length), !projectInfo.isFallbackOpen);
      return projectInfo;
    }

    function refreshProjectInfo(currentInfo, orginNextInfo) {
      var nextInfo = handleDetail(orginNextInfo);
      if (!_.isEqual(currentInfo, nextInfo)) {
        if (currentInfo.status === nextInfo.status) {
          if (!_.isEqual(currentInfo.changeGroup, nextInfo.changeGroup)) { currentInfo.changeGroup = nextInfo.changeGroup; }
          if (!_.isEqual(currentInfo.fallbackList, nextInfo.fallbackList)) { currentInfo.fallbackList = nextInfo.fallbackList; }
          currentInfo.undoProjectTask = nextInfo.undoProjectTask;
          currentInfo.undoFallbackTask = nextInfo.undoFallbackTask;
        } else {
          currentInfo = initToggleStatus(nextInfo);
        }
      }
      return currentInfo;
    }
  }
})();